package xconfig

import (
	"context"
	"fmt"
)

// Option ...
type Option func(ConfigCenter)

// ConfigerType ...
type ConfigerType string

type ConfigCenter interface {
	// RegisterObserver register observer return recall func to cancel observer
	RegisterObserver(ctx context.Context, observer *ConfigObserver) (recall func())
	// Stop stop client include cancel client ctx, cancel longpoller ctx, close updateChan
	Stop(ctx context.Context) error
	// GetString get string value form default namespace application
	GetString(ctx context.Context, key string) (string, bool)
	// GetStringWithNamespace get string value form specified namespace
	GetStringWithNamespace(ctx context.Context, namespace, key string) (string, bool)
	// GetBool get bool value form default namespace application
	GetBool(ctx context.Context, key string) (bool, bool)
	// GetBoolWithNamespace get bool value form specified namespace
	GetBoolWithNamespace(ctx context.Context, namespace, key string) (bool, bool)
	// GetInt get int value form default namespace application
	GetInt(ctx context.Context, key string) (int, bool)
	// GetIntWithNamespace get int value form specified namespace
	GetIntWithNamespace(ctx context.Context, namespace, key string) (int, bool)
	// GetInt64 get int64 value form default namespace application
	GetInt64(ctx context.Context, key string) (int64, bool)
	// GetInt64WithNamespace get int64 value form specified namespace
	GetInt64WithNamespace(ctx context.Context, namespace, key string) (int64, bool)
	// GetInt32 get int32 value form default namespace application
	GetInt32(ctx context.Context, key string) (int32, bool)
	// GetInt32WithNamespace get int32 value form specified namespace
	GetInt32WithNamespace(ctx context.Context, namespace, key string) (int32, bool)
	// GetFloat64 get float64 value form default namespace application
	GetFloat64(ctx context.Context, key string) (float64, bool)
	// GetFloat64WithNamespace get float64 value form specified namespace
	GetFloat64WithNamespace(ctx context.Context, namespace, key string) (float64, bool)
	// GetAllKeys get all keys from default namespace application
	GetAllKeys(ctx context.Context) []string
	// GetAllKeysWithNamespace get all keys form specified namespace
	GetAllKeysWithNamespace(ctx context.Context, namespace string) []string
	// Unmarshal unmarshal from default namespace application
	Unmarshal(ctx context.Context, v interface{}) error
	// UnmarshalWithNamespace unmarshal form specified namespace
	UnmarshalWithNamespace(ctx context.Context, namespace string, v interface{}) error
	// UnmarshalKey unmarshal key from default namespace application
	UnmarshalKey(ctx context.Context, key string, v interface{}) error
	// UnmarshalKeyWithNamespace unmarshal key form specified namespace
	UnmarshalKeyWithNamespace(ctx context.Context, namespace string, key string, v interface{}) error
}

// NewConfigCenter ...
func NewConfigCenter(ctx context.Context, ctype ConfigerType, cfgroot string, serviceName string, namespaceNames []string, options ...Option) (ConfigCenter, error) {
	driver, err := GetDriver(ctype)
	if err != nil {
		return nil, fmt.Errorf("new config center err:%s", err.Error())
	}
	return driver.New(ctx, cfgroot, serviceName, namespaceNames, options...)
}
